From: Philippe Antoine Date: Wed, 18 Feb 2026 14:00:08 +0000 (+0100) Subject: [PATCH] dcerpc: use take instead of split_off(0) X-Git-Tag: archive/raspbian/1%7.0.10-1+rpi1+deb13u4^2~1 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=9e51ab4e76d811e86b09fc51d38ec8f171405449;p=suricata.git [PATCH] dcerpc: use take instead of split_off(0) Ticket: 8304 Avoids quadratic complexity. With split_off(0), the whole vec is copied, so if wa have other calls supplying one byte at a time, we keep on copying increasing data Origin: upstream, https://github.com/OISF/suricata/commit/281f419c0481f7d24d8ce5482b962673a3938e9b.patch Bug: https://redmine.openinfosecfoundation.org/issues/8304 Subject: Upstream fix for CVE-2026-31937 Gbp-Pq: Name CVE-2026-31937.patch --- diff --git a/rust/src/dcerpc/dcerpc.rs b/rust/src/dcerpc/dcerpc.rs index 75fc151c..22baf69f 100644 --- a/rust/src/dcerpc/dcerpc.rs +++ b/rust/src/dcerpc/dcerpc.rs @@ -467,18 +467,6 @@ impl DCERPCState { self.bytes_consumed = 0; } - pub fn extend_buffer(&mut self, buffer: &[u8], direction: Direction) { - match direction { - Direction::ToServer => { - self.buffer_ts.extend_from_slice(buffer); - } - Direction::ToClient => { - self.buffer_tc.extend_from_slice(buffer); - } - } - self.data_needed_for_dir = direction; - } - pub fn reset_direction(&mut self, direction: Direction) { if direction == Direction::ToServer { self.data_needed_for_dir = Direction::ToClient; @@ -965,24 +953,24 @@ impl DCERPCState { self.data_needed_for_dir = direction; } - let buffer = match direction { + let mut buffer = match direction { Direction::ToServer => { if self.buffer_ts.len() + input_len > 1024 * 1024 { SCLogDebug!("DCERPC TOSERVER stream: Buffer Overflow"); return AppLayerResult::err(); } - v = self.buffer_ts.split_off(0); + v = std::mem::take(&mut self.buffer_ts); v.extend_from_slice(cur_i); - v.as_slice() + v } Direction::ToClient => { if self.buffer_tc.len() + input_len > 1024 * 1024 { SCLogDebug!("DCERPC TOCLIENT stream: Buffer Overflow"); return AppLayerResult::err(); } - v = self.buffer_tc.split_off(0); + v = std::mem::take(&mut self.buffer_tc); v.extend_from_slice(cur_i); - v.as_slice() + v } }; @@ -996,9 +984,16 @@ impl DCERPCState { // Check if header data was complete. In case of EoF or incomplete data, wait for more // data else return error if self.bytes_consumed < DCERPC_HDR_LEN.into() && input_len > 0 { - parsed = self.process_header(buffer); + parsed = self.process_header(buffer.as_slice()); if parsed == -1 { - self.extend_buffer(buffer, direction); + match direction { + Direction::ToServer => { + self.buffer_ts = std::mem::take(&mut buffer); + } + Direction::ToClient => { + self.buffer_tc = std::mem::take(&mut buffer); + } + } return AppLayerResult::ok(); } if parsed == -2 { @@ -1011,7 +1006,14 @@ impl DCERPCState { if (buffer.len()) < fraglen as usize { SCLogDebug!("Possibly fragmented data, waiting for more.."); - self.extend_buffer(buffer, direction); + match direction { + Direction::ToServer => { + self.buffer_ts = std::mem::take(&mut buffer); + } + Direction::ToClient => { + self.buffer_tc = std::mem::take(&mut buffer); + } + } return AppLayerResult::ok(); } else { self.query_completed = true;